package cwinsor.raking.year2014;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * This class is a person
 * This class is abstract
 * A person has properties - name, gender, phone number, etc.
 *  Properties are held in a map <PROPERTY_ENUM, RakerProperty>
 */
public abstract class Person {

	// map from property (enum) to a property (object)
	private Map<PROP_E, PropertyBase> propMap = new HashMap<PROP_E, PropertyBase>();

	/*
	 * constructor
	 */
	public Person() {
	}

	/* 
	 * take in a csv parser (parsed string) populate the fields
	 */
	public void fromCsvAllFields(CsvParseRakers csvParser) {

		setProp(PROP_E.FIRST_NAME, csvParser);
		setProp(PROP_E.LAST_NAME, csvParser);
		setProp(PROP_E.POWER, csvParser);
		setProp(PROP_E.COACH, csvParser);
		setProp(PROP_E.GENDER, csvParser);
		setProp(PROP_E.VARSITY_NOVICE, csvParser);
		setProp(PROP_E.GRADE, csvParser);

		setPropVirt(PROP_E.HAPPINESS, new PropertyVirtualHappiness(), propMap); // virtual property

		// preference
		setProp(PROP_E.RP02AM, csvParser);
		setProp(PROP_E.RP02PM, csvParser);
		setProp(PROP_E.RP03AM, csvParser);
		setProp(PROP_E.RP03PM, csvParser);
		setProp(PROP_E.RP09AM, csvParser);
		setProp(PROP_E.RP09PM, csvParser);
		setProp(PROP_E.RP10AM, csvParser);
		setProp(PROP_E.RP10PM, csvParser);

		// last preference
		setProp(PROP_E.RLP02AM, csvParser);
		setProp(PROP_E.RLP02PM, csvParser);
		setProp(PROP_E.RLP03AM, csvParser);
		setProp(PROP_E.RLP03PM, csvParser);
		setProp(PROP_E.RLP09AM, csvParser);
		setProp(PROP_E.RLP09PM, csvParser);
		setProp(PROP_E.RLP10AM, csvParser);
		setProp(PROP_E.RLP10PM, csvParser);

		// team assignment
		setProp(PROP_E.TA02AM, csvParser);
		setProp(PROP_E.TA02PM, csvParser);
		setProp(PROP_E.TA03AM, csvParser);
		setProp(PROP_E.TA03PM, csvParser);
		setProp(PROP_E.TA09AM, csvParser);
		setProp(PROP_E.TA09PM, csvParser);
		setProp(PROP_E.TA10AM, csvParser);
		setProp(PROP_E.TA10PM, csvParser);
	}



	/* 
	 * take in a preferences update parser (parsed string) update raker preferences
	 */
	public void fromCsvNewSchedulePreferences(CsvParseRakers csvParser) {

		// set last preference from current
		{
			PROP_E[] fromList = PROP_E.curPrefsList();
			PROP_E[] toList = PROP_E.lastPrefsList();
			for (int i=0; i<fromList.length; i++) {
				propMap.put(toList[i], this.getProp(fromList[i]));
			}
		}

		// set current preferences from file
		{
			PROP_E[] list = PROP_E.curPrefsList();
			for (int i=0; i<list.length; i++) {
				propMap.put(list[i], csvParser.getProp(list[i]));
			}
		}
	}


	/*
	 *  return a csv-delimited string representation
	 */
	public String toCsvAllFields(CsvParseRakers csvParser) {

		CsvParseRakers csvParseRakers = new CsvParseRakers();
		String string = csvParseRakers.generate(this);
		return string;
	}

	/*
	 * set property (from csv parser)
	 */
	private void setProp(PROP_E propE, CsvParseRakers csvParser) {
		propMap.put(propE, csvParser.getProp(propE));
	}

	/*
	 * set property (physical)
	 */
	private void setPropPhys(PROP_E propE, PropertyBase propO) {
		propMap.put(propE, propO);
	}

	/*
	 * set property (virtual)
	 */
	private void setPropVirt(PROP_E propE, PropertyBase propO, Map<PROP_E, PropertyBase> propMap) {
		propMap.put(propE, propO);
		propO.setPropertySourcesForVal(propMap);
	}

	/*
	 * get property
	 */
	public PropertyBase getProp(PROP_E propE) {
		return propMap.get(propE);
	}




	/*
	 * For physical properties - set all property values
	 * given an array of fields, and an index into the fields (column number)
	 * This does two things - adds to the local <PROPERTY_ENUM,column_number> map
	 * and sets the value in the property instance itself - taken from the column_number
	 */
	/*
	void setPropValFromStrArr(
			PROPERTY propE,
			String[] fieldArray,
			int colm) {

		PrsnPropBase propO = get(propE);
		column.put(propE, colm);

		// it turns out that if there are no elements at the end, csvFileReader will truncate the line
		// watch for this case
		if (colm >= fieldArray.length) {
			Msg.fatal(dS + ": input string doesn't have enough columns - colm " + colm + " fieldArray.length" + fieldArray.length);
		}
		else {
			propO.setPropertyValFromString(fieldArray[colm]);
		}
	}
	 */

	/*
	 * For virtual properties - set the source from which it can compute it's value.
	 * This gives the property map to the property instance.
	 */
	/*
	private void setVirtualPropSources(PROPERTY propE, Map<PROPERTY, PrsnPropBase> theMap) {
		PrsnPropBase propO = get(propE);
		propO.setPropertySourcesForVal(theMap);
	}
	 */

	public void agePreferences(CsvParseRakers csvParser) {

		// copy current preferences to last preferences
		{
			PROP_E[] fromList = PROP_E.curPrefsList();
			PROP_E[] toList = PROP_E.lastPrefsList();
			for (int i = 0; i < fromList.length; i++) {
				setPropPhys(toList[i], getProp(fromList[i]));
			}
		}

		// if no preferences are indicates 
		// copy new preferences (from updates instance given to us) to current preferences
		if (!noPreferencesIndicated()) {
			PROP_E[] fromToList = PROP_E.curPrefsList();
			for (int i = 0; i < fromToList.length; i++) {
				setPropPhys(fromToList[i], csvParser.getProp(fromToList[i]));
			}
		}
	}

	/*
	 * returns true if all fields associated with current preferences are "0" (not filled in)
	 */
	private boolean noPreferencesIndicated() {
		for (PROP_E p : PROP_E.curPrefsList()) {
			if (!this.getProp(p).toInteger().equals(0)) {
				return false;
			}
		}
		return true;
	}


	/*
	 * comparison operator
	 */
	public Boolean sameName(PersonRaker other) {

		return this.getProp(PROP_E.FIRST_NAME).toString().equals(
				other.getProp(PROP_E.FIRST_NAME).toString()) &&
				this.getProp(PROP_E.LAST_NAME).toString().equals(
						other.getProp(PROP_E.LAST_NAME).toString());
	}



	// debug string, debug level
	String  dS = this.getClass().getSimpleName();
	Integer dL = 0;
}

